// 编译器提供了一些内置的派生 trait #[derive]，可以自动实现一些常见功能。
// 例如，我们可以使用 `Debug` 自动实现 `Display` trait，反之亦然。
// 我们也可以使用 `Clone` 自动实现 `Copy` trait，反之亦然。
// 还有很多其他的派生 trait，可以自动实现一些常见功能。
// 这些功能可以帮助我们减少代码量，提高代码的可读性和可维护性。

// 比较常用的派生 trait 有：Eq, PartialEq, Ord, PartialOrd
// Clone, 通过COPY实现Clone &T 创建 T
// Copy, 给一个类型 copy语义， 不是移动语义
// Hash， 从&T 计算哈希值
// Default, 创建一个数据类型的空实例
// Debug, 格式化一个值，使用 {:?} 格式

// `Centimeters`, a tuple struct that can be compared
#[derive(PartialEq, PartialOrd)]
struct Centimeters(f64);

// `Inches`, a tuple struct that can be printed
#[derive(Debug)]
struct Inches(i32);

impl Inches {
    fn to_centimeters(&self) -> Centimeters {
        // 这里发生了解构，提取 Inches 中的 i32 值到 inches
        let &Inches(inches) = self;
        // 这样可以转换为f64， 为什么可以转？
        Centimeters(inches as f64 * 2.54)
    }
}

// `Seconds`, a tuple struct with no additional attributes
struct Seconds(i32);

fn main() {
    let _one_second = Seconds(1);

    // Error: `Seconds` can't be printed; it doesn't implement the `Debug` trait
    // println!("One second looks like: {:?}", _one_second);
    // TODO ^ Try uncommenting this line

    // Error: `Seconds` can't be compared; it doesn't implement the `PartialEq` trait
    // let _this_is_true = (_one_second == _one_second);
    // TODO ^ Try uncommenting this line

    let foot = Inches(12);

    println!("One foot equals {:?}", foot);

    let meter = Centimeters(100.0);

    let cmp = if foot.to_centimeters() < meter {
        "smaller"
    } else {
        "bigger"
    };

    println!("One foot is {} than one meter.", cmp);
}
